from PyQt5.QtWidgets import (
    QWidget, QVBoxLayout, QHBoxLayout, QPushButton, QTableWidget, QTableWidgetItem,
    QHeaderView, QMessageBox, QAbstractItemView, QDialog, QFormLayout, QLineEdit,
    QLabel, QComboBox, QDateEdit, QGroupBox, QDoubleSpinBox, QDialogButtonBox, QGridLayout,
    QFrame, QSizePolicy
)
from PyQt5.QtGui import QColor, QIcon, QFont, QPalette
from PyQt5.QtCore import Qt, QDate, QSize
import datetime
import re


# ======================
# 全局样式配置
# ======================
PRIMARY_COLOR = "#3498db"  # 蓝色
SECONDARY_COLOR = "#2ecc71"  # 绿色
WARNING_COLOR = "#f39c12"  # 橙色
DANGER_COLOR = "#e74c3c"  # 红色
INFO_COLOR = "#2980b9"  # 深蓝色
DISABLED_COLOR = "#bdc3c7"  # 灰色
BG_COLOR = "#ecf0f1"  # 浅灰色背景
TEXT_COLOR = "#2c3e50"  # 深灰色文字
ACCENT_COLOR = "#6a5acd"  # 紫罗兰色增强视觉层次

# 字体配置 - 增大尺寸提高清晰度
HEADER_FONT = QFont("Microsoft YaHei UI", 11, QFont.Bold)
INPUT_FONT = QFont("Microsoft YaHei UI", 11)
BUTTON_FONT = QFont("Microsoft YaHei UI", 11, QFont.Bold)
TABLE_HEADER_FONT = QFont("Microsoft YaHei UI", 11, QFont.Bold)
TABLE_FONT = QFont("Microsoft YaHei UI", 10)
DIALOG_TITLE_FONT = QFont("Microsoft YaHei UI", 14, QFont.Bold)  # 对话框标题字体


def DARKEN(color, percent):
    """使颜色变暗"""
    match = re.match(r"#([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})", color)
    if not match:
        return color
    r, g, b = match.groups()
    r, g, b = [int(x, 16) for x in (r, g, b)]
    r = max(0, int(r * (1 - percent / 100)))
    g = max(0, int(g * (1 - percent / 100)))
    b = max(0, int(b * (1 - percent / 100)))
    return f"#{r:02x}{g:02x}{b:02x}"


def apply_stylesheet(widget=None):
    """应用全局样式表 - 优化清晰度"""
    # 信息按钮样式
    info_button = f"""
        QPushButton {{
            background-color: {INFO_COLOR};
            color: white;
            min-width: 120px;
        }}
        QPushButton:hover {{
            background-color: #1a5a82;
        }}
    """

    style_sheet = f"""
        QWidget {{
            background-color: {BG_COLOR};
            color: {TEXT_COLOR};
            font-family: "Microsoft YaHei UI";
        }}

        QGroupBox {{
            border: 1px solid {PRIMARY_COLOR};
            border-radius: 8px;
            margin-top: 1.5em;
            padding-top: 10px;
        }}

        QGroupBox::title {{
            subcontrol-origin: margin;
            subcontrol-position: top left;
            padding: 4px 12px;
            background-color: {PRIMARY_COLOR};
            color: white;
            border-radius: 4px;
            font-weight: bold;
            font-size: 11pt;
        }}

        QLineEdit, QComboBox, QDateEdit, QDoubleSpinBox, QTextEdit {{
            background-color: white;
            border: 2px solid #a0a0a0;
            border-radius: 5px;
            padding: 8px 12px;
            min-height: 40px;
            font-size: 11pt;
            font-weight: 500;
            color: #333333;
        }}

        QLineEdit:focus, QComboBox:focus, QDateEdit:focus, QDoubleSpinBox:focus {{
            border: 2px solid {PRIMARY_COLOR};
        }}

        QPushButton {{
            background-color: {PRIMARY_COLOR};
            color: white;
            border-radius: 5px;
            padding: 10px 20px;
            min-width: 100px;
            min-height: 40px;
            font-weight: bold;
            font-size: 11pt;
        }}

        QPushButton:hover {{
            background-color: #2980b9;
        }}

        QPushButton:pressed {{
            background-color: {DARKEN(PRIMARY_COLOR, 15)};
        }}

        QPushButton:disabled {{
            background-color: {DISABLED_COLOR};
        }}

        QTableWidget {{
            background-color: white;
            gridline-color: #d0d0d0;
            border-radius: 6px;
        }}

        QHeaderView::section {{
            background-color: {PRIMARY_COLOR};
            color: white;
            padding: 10px;
            font-size: 11pt;
            font-weight: bold;
            border: none;
        }}

        QLabel {{
            font-weight: bold;
            font-size: 11pt;
        }}

        QTabWidget::pane {{
            border: 1px solid {PRIMARY_COLOR};
            border-radius: 8px;
            background: white;
        }}

        QTabBar::tab {{
            background: #ecf0f1;
            color: {TEXT_COLOR};
            border: 1px solid #bdc3c7;
            border-bottom-color: #bdc3c7;
            border-top-left-radius: 8px;
            border-top-right-radius: 8px;
            padding: 10px 20px;
            margin-right: 5px;
            min-width: 120px;
            font-weight: bold;
            font-size: 11pt;
        }}

        QTabBar::tab:selected {{
            background: {PRIMARY_COLOR};
            color: white;
            border-bottom-color: {PRIMARY_COLOR};
        }}

        QTabBar::tab:hover {{
            background: #d6e6f2;
        }}
    """

    # 特殊按钮样式
    success_button = f"""
        QPushButton {{
            background-color: {SECONDARY_COLOR};
        }}
        QPushButton:hover {{
            background-color: #27ae60;
        }}
    """

    danger_button = f"""
        QPushButton {{
            background-color: {DANGER_COLOR};
        }}
        QPushButton:hover {{
            background-color: #c0392b;
        }}
    """

    warning_button = f"""
        QPushButton {{
            background-color: {WARNING_COLOR};
        }}
        QPushButton:hover {{
            background-color: #d35400;
        }}
    """

    if widget:
        widget.setStyleSheet(style_sheet)
    return {
        "global": style_sheet,
        "success": success_button,
        "danger": danger_button,
        "warning": warning_button,
        "info": info_button  # 添加 info 样式
    }




class OpenAccountDialog(QDialog):
    """开卡对话框 - 优化布局版"""

    def __init__(self, db, parent=None):
        super().__init__(parent)
        self.db = db
        self.styles = apply_stylesheet(self)
        self.setWindowTitle("银行卡开卡")
        self.setWindowIcon(QIcon(":/icons/card.png"))
        self.setFixedSize(850, 750)  # 增大对话框尺寸
        self.init_ui()

    def init_ui(self):
        main_layout = QVBoxLayout(self)
        main_layout.setContentsMargins(30, 25, 30, 25)  # 增加内边距
        main_layout.setSpacing(25)  # 增加组件间距

        # 标题区域
        title_layout = QVBoxLayout()
        title_layout.setSpacing(10)

        title_label = QLabel("银行卡开卡")
        title_label.setFont(QFont("Microsoft YaHei UI", 16, QFont.Bold))
        title_label.setStyleSheet(f"color: {PRIMARY_COLOR};")
        title_label.setAlignment(Qt.AlignCenter)
        title_layout.addWidget(title_label)

        # 添加分隔线
        separator = QFrame()
        separator.setFrameShape(QFrame.HLine)
        separator.setFrameShadow(QFrame.Sunken)
        separator.setStyleSheet(f"background-color: {PRIMARY_COLOR}; height: 2px;")
        separator.setFixedHeight(2)
        title_layout.addWidget(separator)

        main_layout.addLayout(title_layout)

        # 客户信息组 - 使用表单布局提升可读性
        info_group = QGroupBox("客户信息")
        info_group.setFont(QFont("Microsoft YaHei UI", 12, QFont.Bold))
        form_layout = QFormLayout()
        form_layout.setVerticalSpacing(20)  # 增加行间距
        form_layout.setHorizontalSpacing(25)  # 增加列间距
        form_layout.setFieldGrowthPolicy(QFormLayout.FieldsStayAtSizeHint)

        # 姓名
        self.customer_name = QLineEdit()
        self.customer_name.setFont(QFont("Microsoft YaHei UI", 11))
        self.customer_name.setPlaceholderText("请输入客户姓名")
        self.customer_name.setMinimumHeight(40)
        form_layout.addRow("姓名:", self.customer_name)

        # 身份证号
        self.pid = QLineEdit()
        self.pid.setFont(QFont("Microsoft YaHei UI", 11))
        self.pid.setPlaceholderText("请输入18位身份证号码")
        self.pid.setMaxLength(18)
        form_layout.addRow("身份证号:", self.pid)

        # 手机号码
        self.phone = QLineEdit()
        self.phone.setFont(QFont("Microsoft YaHei UI", 11))
        self.phone.setPlaceholderText("请输入11位手机号码")
        self.phone.setMaxLength(11)
        form_layout.addRow("手机号码:", self.phone)

        info_group.setLayout(form_layout)
        main_layout.addWidget(info_group)

        # 银行卡信息组 - 同样使用表单布局
        card_group = QGroupBox("银行卡信息")
        card_group.setFont(QFont("Microsoft YaHei UI", 12, QFont.Bold))
        card_layout = QFormLayout()
        card_layout.setVerticalSpacing(20)
        card_layout.setHorizontalSpacing(25)
        card_layout.setFieldGrowthPolicy(QFormLayout.FieldsStayAtSizeHint)

        # 存款类型
        self.saving_type = QComboBox()
        self.saving_type.setFont(QFont("Microsoft YaHei UI", 11))
        self.saving_type.addItems(["活期存款(1)", "定活两便(2)", "整存整取(3)", "零存整取(4)"])
        self.saving_type.setCurrentIndex(0)
        card_layout.addRow("存款类型:", self.saving_type)

        # 开户金额
        self.open_money = QDoubleSpinBox()
        self.open_money.setFont(QFont("Microsoft YaHei UI", 11))
        self.open_money.setRange(1.00, 1000000.00)
        self.open_money.setValue(1000.00)
        self.open_money.setPrefix("¥ ")
        self.open_money.setSuffix(" 元")
        self.open_money.setButtonSymbols(QDoubleSpinBox.NoButtons)
        card_layout.addRow("开户金额:", self.open_money)

        card_group.setLayout(card_layout)
        main_layout.addWidget(card_group)

        # 按钮区域
        button_layout = QHBoxLayout()
        button_layout.setContentsMargins(50, 20, 50, 0)

        ok_button = QPushButton("确认开卡")
        ok_button.setFont(QFont("Microsoft YaHei UI", 12, QFont.Bold))
        ok_button.setStyleSheet(self.styles["success"] + "padding: 10px 20px;")
        ok_button.setMinimumSize(150, 50)
        ok_button.clicked.connect(self.accept)

        cancel_button = QPushButton("取消")
        cancel_button.setFont(QFont("Microsoft YaHei UI", 12, QFont.Bold))
        cancel_button.setStyleSheet(self.styles["danger"] + "padding: 10px 20px;")
        cancel_button.setMinimumSize(150, 50)
        cancel_button.clicked.connect(self.reject)

        button_layout.addStretch()
        button_layout.addWidget(ok_button)
        button_layout.addSpacing(30)
        button_layout.addWidget(cancel_button)
        button_layout.addStretch()

        main_layout.addLayout(button_layout)

    def create_h_separator(self):
        """创建水平分隔线"""
        line = QFrame()
        line.setFrameShape(QFrame.HLine)
        line.setFrameShadow(QFrame.Sunken)
        line.setStyleSheet(f"background-color: {DARKEN(BG_COLOR, 15)};")
        return line

    def get_data(self):
        return {
            'p_name': self.customer_name.text().strip(),
            'p_pid': self.pid.text().strip(),
            'p_phone': self.phone.text().strip(),
            'p_savingID': self.saving_type.currentIndex() + 1,
            'p_openMoney': self.open_money.value()
        }

    def validate(self):
        if not self.customer_name.text().strip():
            QMessageBox.warning(self, "验证失败", "客户姓名不能为空")
            return False

        pid = self.pid.text().strip()
        if len(pid) != 18 or not pid.isdigit():
            QMessageBox.warning(self, "验证失败", "身份证号必须是18位数字")
            return False

        phone = self.phone.text().strip()
        if len(phone) != 11 or not phone.isdigit():
            QMessageBox.warning(self, "验证失败", "手机号码必须是11位数字")
            return False

        return True


class CloseAccountDialog(QDialog):
    """销户对话框"""

    def __init__(self, db, total_balance, customer_id, customer_info, parent=None):
        super().__init__(parent)
        self.db = db
        self.total_balance = total_balance
        self.styles = apply_stylesheet(self)
        self.customer_id = customer_id  # 关键：新增客户ID属性
        self.customer_info = customer_info  # 存储客户信息
        self.setWindowTitle("客户销户")
        self.setWindowIcon(QIcon(":/icons/delete.png"))
        self.setFixedSize(850, 850)
        self.card_valid = False
        self.init_ui()

    def init_ui(self):
        main_layout = QVBoxLayout()
        main_layout.setContentsMargins(30, 25, 30, 25)  # 增加内边距
        main_layout.setSpacing(25)  # 增加组件间距

        # 添加余额警告
        if self.total_balance > 0:
            # 余额警告
            balance_label = QLabel(f"警告：该客户仍有 ¥{self.total_balance:.2f} 元余额！")
            balance_label.setFont(QFont("Microsoft YaHei UI", 11, QFont.Bold))
            balance_label.setStyleSheet(f"color: {DANGER_COLOR}; background-color: #ffcccc; padding: 10px;")
            balance_label.setAlignment(Qt.AlignCenter)
            main_layout.addWidget(balance_label)

            # 转账说明
            transfer_label = QLabel("请将余额转账到其他银行卡:")
            transfer_label.setFont(QFont("Microsoft YaHei UI", 11))
            main_layout.addWidget(transfer_label)

            # 转账目标卡号
            transfer_layout = QHBoxLayout()
            transfer_layout.addWidget(QLabel("转账目标卡号:"))
            self.transfer_to_card = QLineEdit()
            self.transfer_to_card.setPlaceholderText("请输入有效的银行卡号")
            transfer_layout.addWidget(self.transfer_to_card)

            # 验证卡号按钮
            validate_btn = QPushButton("验证卡号")
            validate_btn.setStyleSheet(self.styles["info"])
            validate_btn.clicked.connect(self.validate_card)
            transfer_layout.addWidget(validate_btn)

            main_layout.addLayout(transfer_layout)

            # 验证状态提示
            self.card_validation = QLabel("")
            self.card_validation.setStyleSheet(f"color: {DANGER_COLOR};")
            main_layout.addWidget(self.card_validation)

            main_layout.addSpacing(15)
        # 标题区域
        title_layout = QVBoxLayout()
        title_label = QLabel("客户销户")
        title_label.setFont(QFont("Microsoft YaHei UI", 16, QFont.Bold))
        title_label.setStyleSheet(f"color: {DANGER_COLOR};")
        title_label.setAlignment(Qt.AlignCenter)
        title_layout.addWidget(title_label)

        # 添加分隔线
        separator = QFrame()
        separator.setFrameShape(QFrame.HLine)
        separator.setFrameShadow(QFrame.Sunken)
        separator.setStyleSheet(f"background-color: {DANGER_COLOR}; height: 2px;")
        separator.setFixedHeight(2)
        title_layout.addWidget(separator)

        main_layout.addLayout(title_layout)

        # 警告标签
        warning_label = QLabel("警告：此操作将永久删除客户账户信息，无法恢复！")
        warning_label.setFont(QFont("Microsoft YaHei UI", 12, QFont.Bold))
        warning_label.setStyleSheet(f"color: {DANGER_COLOR}; padding: 10px;")
        warning_label.setAlignment(Qt.AlignCenter)
        main_layout.addWidget(warning_label)

        group = QGroupBox("客户信息")
        group.setFont(QFont("Microsoft YaHei UI", 12, QFont.Bold))
        form_layout = QFormLayout()  # 使用QFormLayout避免错误
        form_layout.setVerticalSpacing(25)  # 增加行间距
        form_layout.setHorizontalSpacing(30)  # 增加列间距

        # 姓名
        self.customer_name = QLineEdit()
        self.customer_name.setFont(QFont("Microsoft YaHei UI", 11))
        self.customer_name.setPlaceholderText("请输入客户姓名")
        self.customer_name.setMinimumHeight(40)
        form_layout.addRow("姓名:", self.customer_name)

        # 身份证号
        self.pid = QLineEdit()
        self.pid.setFont(QFont("Microsoft YaHei UI", 11))
        self.pid.setPlaceholderText("请输入18位身份证号码")
        self.pid.setMaxLength(18)
        self.pid.setMinimumHeight(40)
        form_layout.addRow("身份证号:", self.pid)

        # 手机号码
        self.phone = QLineEdit()
        self.phone.setFont(QFont("Microsoft YaHei UI", 11))
        self.phone.setPlaceholderText("请输入11位手机号码")
        self.phone.setMaxLength(11)
        self.phone.setMinimumHeight(40)
        form_layout.addRow("手机号码:", self.phone)

        group.setLayout(form_layout)
        main_layout.addWidget(group)

        # 按钮区域
        button_layout = QHBoxLayout()
        button_layout.setContentsMargins(50, 20, 50, 0)

        ok_button = QPushButton("确认销户")
        ok_button.setFont(QFont("Microsoft YaHei UI", 12, QFont.Bold))
        ok_button.setStyleSheet(self.styles["danger"] + "padding: 10px 20px;")
        ok_button.setMinimumSize(150, 50)
        ok_button.clicked.connect(self.accept)

        cancel_button = QPushButton("取消")
        cancel_button.setFont(QFont("Microsoft YaHei UI", 12, QFont.Bold))
        ok_button.setStyleSheet(self.styles["danger"] + "padding: 10px 20px;")
        cancel_button.setStyleSheet("background-color: #555; color: white; padding: 10px 20px;")
        cancel_button.setMinimumSize(150, 50)
        cancel_button.clicked.connect(self.reject)

        button_layout.addStretch()
        button_layout.addWidget(ok_button)
        button_layout.addSpacing(30)
        button_layout.addWidget(cancel_button)
        button_layout.addStretch()

        main_layout.addLayout(button_layout)
        self.setLayout(main_layout)

    def get_data(self):
        return {
            'p_customerName': self.customer_name.text().strip(),
            'p_pid': self.pid.text().strip(),
            'p_phone': self.phone.text().strip()
        }

    def validate(self):
        errors = []

        if not self.customer_name.text().strip():
            errors.append("客户姓名不能为空")

        pid = self.pid.text().strip()
        if len(pid) != 18 or not pid.isdigit():
            errors.append("身份证号必须是18位数字")

        phone = self.phone.text().strip()
        if len(phone) != 11 or not phone.isdigit():
            errors.append("手机号码必须是11位数字")

        if errors:
            QMessageBox.warning(self, "验证失败", "\n".join(errors))
            return False

        return True

    def create_h_separator(self):
        """创建水平分隔线"""
        line = QFrame()
        line.setFrameShape(QFrame.HLine)
        line.setFrameShadow(QFrame.Sunken)
        line.setStyleSheet(f"background-color: {DARKEN(BG_COLOR, 15)};")
        return line

    def validate_card(self):
        """验证转账目标卡号"""
        card_id = self.transfer_to_card.text().strip()

        if not card_id:
            self.card_validation.setText("请输入银行卡号")
            self.card_validation.setStyleSheet(f"color: {DANGER_COLOR};")
            self.card_valid = False
            return

        # 查询卡号是否存在
        try:
            query = "SELECT COUNT(*) as count FROM cardinfo WHERE cardID = %s"
            result = self.db.execute_query(query, (card_id,))

            if result and result[0]['count'] > 0:
                self.card_validation.setText("✓ 卡号验证通过")
                self.card_validation.setStyleSheet(f"color: {SECONDARY_COLOR};")
                self.card_valid = True
            else:
                self.card_validation.setText("× 卡号不存在")
                self.card_validation.setStyleSheet(f"color: {DANGER_COLOR};")
                self.card_valid = False

        except Exception as e:
            self.card_validation.setText(f"验证失败: {str(e)}")
            self.card_validation.setStyleSheet(f"color: {DANGER_COLOR};")
            self.card_valid = False

    def validate_with_balance(self):
        """检查余额转账是否已正确处理"""
        if self.total_balance > 0:
            # 检查是否填写了转账卡号
            card_id = self.transfer_to_card.text().strip()
            if not card_id:
                QMessageBox.warning(self, "需要转账目标卡号",
                                    "请填写余额转账目标卡号，或取消销户操作")
                return False

            # 检查卡号是否已通过验证
            if not self.card_valid:
                QMessageBox.warning(self, "卡号未验证",
                                    "请点击'验证卡号'按钮确认转账目标卡号有效")
                return False

            try:
                # 获取目标银行卡的客户ID
                query = "SELECT customerID FROM cardinfo WHERE cardID = %s"
                target_customer = self.db.execute_query(query, (card_id,))

                if target_customer:
                    target_id = target_customer[0].get('customerID')

                    # 确保不是转账给自己
                    if target_id == self.customer_id:
                        QMessageBox.warning(self, "转账无效",
                                            "不能将余额转账给自己的其他银行卡")
                        return False

                    # 确保目标客户存在
                    customer_query = "SELECT customerID FROM userinfo WHERE customerID = %s"
                    customer_exists = self.db.execute_query(customer_query, (target_id,))

                    if not customer_exists:
                        QMessageBox.warning(self, "客户不存在",
                                            "转账目标客户不存在，可能已被注销")
                        return False
                else:
                    QMessageBox.warning(self, "银行卡无效",
                                        "未找到指定的银行卡信息")
                    return False
            except Exception as e:
                QMessageBox.critical(self, "验证失败", f"验证转账时出错: {str(e)}")
                return False

        return True




class EditCardDialog(QDialog):
    """银行卡编辑对话框"""

    def __init__(self, db, card_data, parent=None):
        super().__init__(parent)
        self.db = db
        self.card_data = card_data
        self.styles = apply_stylesheet(self)
        self.setWindowTitle("编辑银行卡")
        self.setWindowIcon(QIcon(":/icons/edit.png"))
        self.setFixedSize(850, 750)
        self.init_ui()

    def init_ui(self):
        main_layout = QVBoxLayout()
        main_layout.setContentsMargins(25, 25, 25, 25)
        main_layout.setSpacing(20)

        # 标题
        title_label = QLabel(f"编辑银行卡: {self.card_data['cardID']}")
        title_label.setFont(DIALOG_TITLE_FONT)
        title_label.setStyleSheet(f"color: {PRIMARY_COLOR};")
        title_label.setAlignment(Qt.AlignCenter)
        main_layout.addWidget(title_label)

        # 添加分隔线
        main_layout.addWidget(self.create_h_separator())

        # 银行卡信息表
        form_layout = QFormLayout()
        form_layout.setSpacing(15)
        form_layout.setLabelAlignment(Qt.AlignRight)

        # 存款类型
        saving_type_label = QLabel("存款类型:")
        saving_type_label.setFont(INPUT_FONT)
        self.saving_type_combo = QComboBox()
        self.saving_type_combo.setFont(INPUT_FONT)
        self.saving_type_combo.addItems(["活期存款(1)", "定活两便(2)", "整存整取(3)", "零存整取(4)"])
        # 设置当前存款类型
        current_type_idx = int(self.card_data.get('savingID', '1')) - 1
        self.saving_type_combo.setCurrentIndex(max(0, min(current_type_idx, 3)))
        form_layout.addRow(saving_type_label, self.saving_type_combo)

        # 挂失状态
        report_loss_label = QLabel("挂失状态:")
        report_loss_label.setFont(INPUT_FONT)
        self.report_loss_combo = QComboBox()
        self.report_loss_combo.setFont(INPUT_FONT)
        self.report_loss_combo.addItems(["正常", "已挂失"])
        # 设置当前挂失状态
        is_report_loss = self.card_data.get('IsReportLoss', '0') == '1'
        self.report_loss_combo.setCurrentIndex(1 if is_report_loss else 0)
        form_layout.addRow(report_loss_label, self.report_loss_combo)

        # 密码 (如果允许管理员重置密码)
        password_label = QLabel("重置密码:")
        password_label.setFont(INPUT_FONT)
        self.password_edit = QLineEdit()
        self.password_edit.setFont(INPUT_FONT)
        self.password_edit.setPlaceholderText("留空则不修改密码")
        self.password_edit.setEchoMode(QLineEdit.Password)
        form_layout.addRow(password_label, self.password_edit)

        # 其他可编辑信息
        balance_label = QLabel("当前余额:")
        balance_label.setFont(INPUT_FONT)
        self.balance_label = QLabel(f"¥{self.card_data.get('balance', '0.00'):.2f}")
        self.balance_label.setFont(INPUT_FONT)
        form_layout.addRow(balance_label, self.balance_label)

        # 开户日期
        open_date_label = QLabel("开户日期:")
        open_date_label.setFont(INPUT_FONT)
        open_date_value = self.card_data.get('openDate', '')
        open_date_text = open_date_value if isinstance(open_date_value, str) else open_date_value.strftime("%Y-%m-%d")
        self.open_date_label = QLabel(open_date_text)
        self.open_date_label.setFont(INPUT_FONT)
        form_layout.addRow(open_date_label, self.open_date_label)

        # 客户姓名 (只读)
        customer_label = QLabel("客户姓名:")
        customer_label.setFont(INPUT_FONT)
        self.customer_label = QLabel(self.card_data.get('customerName', ''))
        self.customer_label.setFont(INPUT_FONT)
        form_layout.addRow(customer_label, self.customer_label)

        main_layout.addLayout(form_layout)

        # 添加分隔线
        main_layout.addWidget(self.create_h_separator())

        # 按钮区域
        button_layout = QHBoxLayout()
        button_layout.setContentsMargins(0, 10, 0, 0)

        ok_button = QPushButton("保存修改")
        ok_button.setFont(BUTTON_FONT)
        ok_button.setStyleSheet(self.styles["success"])
        ok_button.clicked.connect(self.accept)

        cancel_button = QPushButton("取消")
        cancel_button.setFont(BUTTON_FONT)
        cancel_button.setStyleSheet(self.styles["danger"])
        cancel_button.clicked.connect(self.reject)

        button_layout.addStretch()
        button_layout.addWidget(ok_button)
        button_layout.addWidget(cancel_button)

        main_layout.addLayout(button_layout)
        self.setLayout(main_layout)

    def create_h_separator(self):
        """创建水平分隔线"""
        line = QFrame()
        line.setFrameShape(QFrame.HLine)
        line.setFrameShadow(QFrame.Sunken)
        line.setStyleSheet(f"background-color: {DARKEN(BG_COLOR, 15)};")
        return line

    def get_edited_data(self):
        """获取编辑后的数据"""
        return {
            'card_id': self.card_data['cardID'],
            'saving_id': self.saving_type_combo.currentIndex() + 1,  # 1-4
            'is_report_loss': 1 if self.report_loss_combo.currentText() == "已挂失" else 0,
            'new_password': self.password_edit.text().strip() if self.password_edit.text().strip() else None
        }

class CardTab(QWidget):
    """银行卡管理主界面 - 优化版"""

    def __init__(self, db):
        super().__init__()
        self.db = db
        self.selected_card_id = None
        self.selected_card_status = None
        self.selected_card_data = None
        self.styles = apply_stylesheet(self)
        self.init_ui()

    def init_ui(self):
        # 主布局
        main_layout = QVBoxLayout()
        main_layout.setContentsMargins(20, 20, 20, 20)
        main_layout.setSpacing(20)

        # 标题区域
        title_layout = QHBoxLayout()
        title_label = QLabel("银行卡管理")
        title_label.setFont(QFont("Microsoft YaHei UI", 16, QFont.Bold))
        title_label.setStyleSheet(f"color: {PRIMARY_COLOR};")
        title_layout.addWidget(title_label)
        title_layout.addStretch()

        refresh_button = QPushButton(QIcon(":/icons/refresh.png"), "刷新")
        refresh_button.setFont(BUTTON_FONT)
        refresh_button.setStyleSheet(self.styles["warning"])
        refresh_button.clicked.connect(self.load_cards)
        title_layout.addWidget(refresh_button)

        main_layout.addLayout(title_layout)

        # 查询区域
        search_group = QGroupBox("查询条件")
        search_group.setFont(HEADER_FONT)
        search_layout = QGridLayout()
        search_layout.setContentsMargins(15, 20, 15, 15)
        search_layout.setVerticalSpacing(15)
        search_layout.setHorizontalSpacing(15)

        # 第一行
        card_label = QLabel("卡号:")
        card_label.setFont(INPUT_FONT)
        self.card_search = QLineEdit()
        self.card_search.setFont(INPUT_FONT)
        self.card_search.setPlaceholderText("精确查询")
        search_layout.addWidget(card_label, 0, 0)
        search_layout.addWidget(self.card_search, 0, 1, 1, 3)

        # 第二行
        name_label = QLabel("客户姓名:")
        name_label.setFont(INPUT_FONT)
        self.name_search = QLineEdit()
        self.name_search.setFont(INPUT_FONT)
        self.name_search.setPlaceholderText("模糊查询")
        search_layout.addWidget(name_label, 1, 0)
        search_layout.addWidget(self.name_search, 1, 1, 1, 3)

        # 第三行
        type_label = QLabel("存款类型:")
        type_label.setFont(INPUT_FONT)
        self.type_search = QComboBox()
        self.type_search.setFont(INPUT_FONT)

        self.type_search.addItem("所有类型", None)
        self.type_search.addItem("活期存款", 1)
        self.type_search.addItem("定活两便", 2)
        self.type_search.addItem("整存整取", 3)
        self.type_search.addItem("零存整取", 4)
        self.type_search.setCurrentIndex(0)
        search_layout.addWidget(type_label, 2, 0)
        search_layout.addWidget(self.type_search, 2, 1)

        balance_label = QLabel("余额范围:")
        balance_label.setFont(INPUT_FONT)
        search_layout.addWidget(balance_label, 2, 2)

        # 余额范围布局
        min_max_layout = QHBoxLayout()
        min_max_layout.setSpacing(5)

        self.min_balance = QDoubleSpinBox()
        self.min_balance.setFont(INPUT_FONT)
        self.min_balance.setMinimum(0)
        self.min_balance.setMaximum(10000000)
        self.min_balance.setPrefix("¥ ")

        self.max_balance = QDoubleSpinBox()
        self.max_balance.setFont(INPUT_FONT)
        self.min_balance.setMinimum(0)
        self.max_balance.setMaximum(10000000)
        self.max_balance.setPrefix("¥ ")
        self.max_balance.setValue(10000000)

        min_max_layout.addWidget(self.min_balance)
        min_max_layout.addWidget(QLabel("至"))
        min_max_layout.addWidget(self.max_balance)
        search_layout.addLayout(min_max_layout, 2, 3)

        # 查询按钮
        self.search_btn = QPushButton(QIcon(":/icons/search.png"), "查询")
        self.search_btn.setFont(BUTTON_FONT)
        self.search_btn.setStyleSheet(self.styles.get("info", ""))
        self.search_btn.clicked.connect(self.load_cards)
        search_layout.addWidget(self.search_btn, 3, 0, 1, 4, Qt.AlignRight)

        search_group.setLayout(search_layout)
        main_layout.addWidget(search_group)

        # 按钮区域
        btn_group = QGroupBox("操作")
        btn_group.setFont(HEADER_FONT)
        btn_layout = QHBoxLayout()
        btn_layout.setContentsMargins(15, 15, 15, 15)
        btn_layout.setSpacing(10)

        # 添加"编辑"功能按钮
        self.edit_btn = QPushButton(QIcon(":/icons/edit.png"), "编辑")
        self.edit_btn.setFont(BUTTON_FONT)
        self.edit_btn.setToolTip("编辑选中的银行卡")
        self.edit_btn.setStyleSheet(self.styles["info"])
        self.edit_btn.clicked.connect(self.edit_card)
        self.edit_btn.setEnabled(False)

        self.add_btn = QPushButton(QIcon(":/icons/add.png"), "开卡")
        self.add_btn.setFont(BUTTON_FONT)
        self.add_btn.setToolTip("添加新银行卡")
        self.add_btn.setStyleSheet(self.styles["success"])
        self.add_btn.clicked.connect(self.open_account)

        self.report_loss_btn = QPushButton(QIcon(":/icons/lock.png"), "挂失")
        self.report_loss_btn.setFont(BUTTON_FONT)
        self.report_loss_btn.setToolTip("挂失选中的银行卡")
        self.report_loss_btn.setStyleSheet(self.styles["warning"])
        self.report_loss_btn.clicked.connect(self.report_loss)
        self.report_loss_btn.setEnabled(False)

        self.unlock_btn = QPushButton(QIcon(":/icons/unlock.png"), "解挂")
        self.unlock_btn.setFont(BUTTON_FONT)
        self.unlock_btn.setToolTip("解除挂失选中的银行卡")
        self.unlock_btn.setStyleSheet(self.styles["info"])
        self.unlock_btn.clicked.connect(self.unlock_card)
        self.unlock_btn.setEnabled(False)

        self.close_account_btn = QPushButton(QIcon(":/icons/delete.png"), "销户")
        self.close_account_btn.setFont(BUTTON_FONT)
        self.close_account_btn.setToolTip("销户选中的客户")
        self.close_account_btn.setStyleSheet(self.styles["danger"])
        self.close_account_btn.clicked.connect(self.close_account)
        self.close_account_btn.setEnabled(False)

        # 按钮布局 (编辑按钮在开卡按钮后面)
        btn_layout.addWidget(self.add_btn)
        btn_layout.addWidget(self.edit_btn)
        btn_layout.addWidget(self.report_loss_btn)
        btn_layout.addWidget(self.unlock_btn)
        btn_layout.addWidget(self.close_account_btn)
        btn_layout.addStretch()

        btn_group.setLayout(btn_layout)
        main_layout.addWidget(btn_group)

        # 银行卡表格
        self.table = QTableWidget()
        self.table.setFont(TABLE_FONT)
        self.table.setColumnCount(10)
        self.table.setHorizontalHeaderLabels([
            "卡号", "币种", "开户日期", "开户金额",
            "余额", "密码", "挂失状态", "客户ID", "存款类型", "客户姓名"
        ])

        # 设置表头样式
        header = self.table.horizontalHeader()
        header.setFont(TABLE_HEADER_FONT)
        header.setDefaultAlignment(Qt.AlignCenter)
        header.setSectionResizeMode(QHeaderView.Interactive)
        header.setStretchLastSection(True)
        header.setHighlightSections(False)

        # 设置列宽 (增大列宽确保内容完整显示)
        self.table.setColumnWidth(0, 140)  # 卡号
        self.table.setColumnWidth(1, 80)  # 币种
        self.table.setColumnWidth(2, 120)  # 开户日期
        self.table.setColumnWidth(3, 120)  # 开户金额
        self.table.setColumnWidth(4, 120)  # 余额
        self.table.setColumnWidth(5, 80)  # 密码
        self.table.setColumnWidth(6, 100)  # 挂失状态 (增大以容纳"是"或"否")
        self.table.setColumnWidth(7, 80)  # 客户ID
        self.table.setColumnWidth(8, 100)  # 存款类型 (增大以容纳类型名称)
        self.table.setColumnWidth(9, 140)  # 客户姓名

        # 表格设置
        self.table.setAlternatingRowColors(True)
        self.table.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.table.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.table.setSelectionMode(QAbstractItemView.SingleSelection)
        self.table.setSortingEnabled(True)
        self.table.verticalHeader().setVisible(False)
        self.table.itemSelectionChanged.connect(self.on_selection_changed)

        main_layout.addWidget(self.table)
        self.setLayout(main_layout)

        # 初始加载银行卡数据
        self.load_cards()

    def load_cards(self):
        try:
            card_id = self.card_search.text().strip()
            customer_name = self.name_search.text().strip()
            saving_id = self.type_search.currentData()
            min_balance = self.min_balance.value()
            max_balance = self.max_balance.value()

            conditions = []
            params = []

            if card_id:
                conditions.append("c.cardID = %s")
                params.append(card_id)

            if customer_name:
                conditions.append("cu.customerName LIKE %s")
                params.append(f"%{customer_name}%")

            if saving_id is not None:
                conditions.append("c.savingID = %s")
                params.append(saving_id)

            conditions.append("c.balance BETWEEN %s AND %s")
            params.extend([min_balance, max_balance])

            where_clause = " AND ".join(conditions) if conditions else "1=1"

            query = f"""
            SELECT 
                c.cardID, c.curID, c.openDate, c.openMoney, 
                c.balance, c.pass, c.IsReportLoss, c.customerID, 
                c.savingID, cu.customerName
            FROM cardinfo c
            LEFT JOIN userinfo cu ON c.customerID = cu.customerID
            WHERE {where_clause}
            ORDER BY c.openDate DESC
            LIMIT 100
            """

            results = self.db.execute_query(query, params)

            self.table.setRowCount(len(results))

            saving_types = {
                1: "活期存款",
                2: "定活两便",
                3: "整存整取",
                4: "零存整取"
            }

            for row_idx, row in enumerate(results):
                # 保存行数据以备编辑时使用
                row['saving_type_name'] = saving_types.get(row.get('savingID', 1), "未知")

                self.table.setItem(row_idx, 0, self.create_table_item(row.get('cardID', '')))
                self.table.setItem(row_idx, 1, self.create_table_item(row.get('curID', '')))
                self.table.setItem(row_idx, 2, self.format_date(row.get('openDate', '')))
                self.table.setItem(row_idx, 3, self.create_money_item(row.get('openMoney', 0)))
                self.table.setItem(row_idx, 4, self.create_money_item(row.get('balance', 0)))

                # 密码列 - 显示为星号
                password = row.get('pass', '')
                item = QTableWidgetItem("******" if password else "")
                item.setTextAlignment(Qt.AlignCenter)
                self.table.setItem(row_idx, 5, item)

                # 挂失状态
                is_report_loss = row.get('IsReportLoss', 0)
                status_text = "是" if is_report_loss else "否"
                status_item = QTableWidgetItem(status_text)
                status_item.setTextAlignment(Qt.AlignCenter)

                # 根据状态设置颜色
                if is_report_loss:
                    status_item.setBackground(QColor(231, 76, 60, 100))  # 红色背景
                    status_item.setForeground(QColor(192, 57, 43))
                self.table.setItem(row_idx, 6, status_item)

                # 客户ID
                self.table.setItem(row_idx, 7, self.create_table_item(row.get('customerID', '')))

                # 存款类型 - 显示为名称
                saving_id = row.get('savingID', 1)
                saving_name = saving_types.get(saving_id, "未知")
                self.table.setItem(row_idx, 8, self.create_table_item(saving_name))

                # 客户姓名
                self.table.setItem(row_idx, 9, self.create_table_item(row.get('customerName', '')))

            # 设置行高
            self.table.resizeRowsToContents()

        except Exception as e:
            QMessageBox.critical(self, "加载失败", f"加载银行卡数据时出错: {str(e)}")

    def create_table_item(self, value):
        """创建表格项并设置居中"""
        item = QTableWidgetItem(str(value))
        item.setTextAlignment(Qt.AlignCenter)
        return item

    def create_money_item(self, value):
        """创建金额表格项 - 右对齐"""
        item = QTableWidgetItem(f"¥{float(value):.2f}")
        item.setTextAlignment(Qt.AlignRight | Qt.AlignVCenter)
        return item

    def format_date(self, date_value):
        """格式化日期显示"""
        try:
            if isinstance(date_value, datetime.datetime):
                return QTableWidgetItem(date_value.strftime("%Y-%m-%d"))
            return QTableWidgetItem(str(date_value))
        except:
            return QTableWidgetItem("")

    def on_selection_changed(self):
        selected = self.table.selectedItems()
        if selected:
            row = selected[0].row()
            self.selected_card_id = self.table.item(row, 0).text()
            self.selected_card_status = self.table.item(row, 6).text() == "是"

            # 收集选中行的数据
            self.selected_card_data = {
                'cardID': self.table.item(row, 0).text(),
                'curID': self.table.item(row, 1).text(),
                'openDate': self.table.item(row, 2).text(),
                'openMoney': float(self.table.item(row, 3).text().replace('¥', '').strip()),
                'balance': float(self.table.item(row, 4).text().replace('¥', '').strip()),
                'IsReportLoss': self.table.item(row, 6).text(),
                'customerID': self.table.item(row, 7).text(),
                'savingID': self.table.item(row, 8).text(),  # 注意这里保存的是类型名称
                'customerName': self.table.item(row, 9).text()
            }

            # 映射类型名称到ID
            saving_name_to_id = {
                "活期存款": 1,
                "定活两便": 2,
                "整存整取": 3,
                "零存整取": 4
            }

            self.selected_card_data['savingID'] = saving_name_to_id.get(
                self.selected_card_data['savingID'], 1
            )

            # 启用操作按钮
            self.edit_btn.setEnabled(True)
            self.report_loss_btn.setEnabled(True)
            self.unlock_btn.setEnabled(True)
            self.close_account_btn.setEnabled(True)
        else:
            self.selected_card_id = None
            self.selected_card_status = None
            self.selected_card_data = None

            # 禁用操作按钮
            self.edit_btn.setEnabled(False)
            self.report_loss_btn.setEnabled(False)
            self.unlock_btn.setEnabled(False)
            self.close_account_btn.setEnabled(False)

    def edit_card(self):
        """编辑银行卡信息"""
        if not self.selected_card_id or not self.selected_card_data:
            return

        # 创建编辑对话框
        dialog = EditCardDialog(self.db, self.selected_card_data, self)
        if dialog.exec_() == QDialog.Accepted:
            # 获取编辑后的数据
            edited_data = dialog.get_edited_data()

            try:
                # 构建更新语句
                updates = []
                params = []

                # 更新存款类型
                if edited_data['saving_id'] != self.selected_card_data['savingID']:
                    updates.append("savingID = %s")
                    params.append(edited_data['saving_id'])

                # 更新挂失状态
                new_report_loss = 1 if edited_data['is_report_loss'] == 1 else 0
                current_report_loss = 1 if self.selected_card_data.get('IsReportLoss') == "是" else 0
                if new_report_loss != current_report_loss:
                    updates.append("IsReportLoss = %s")
                    params.append(new_report_loss)

                # 更新密码
                if edited_data['new_password']:
                    # 实际应用中应使用加密存储密码
                    updates.append("pass = %s")
                    params.append(edited_data['new_password'])

                # 如果有字段更新
                if updates:
                    # 设置更新SQL语句
                    set_clause = ", ".join(updates)
                    query = f"UPDATE cardinfo SET {set_clause} WHERE cardID = %s"
                    params.append(self.selected_card_id)

                    # 执行更新
                    result = self.db.execute_query(query, params)
                    if result is not None:
                        # 提交事务
                        self.db.commit()
                        QMessageBox.information(self, "成功", "银行卡信息已更新")
                        self.load_cards()
                    else:
                        QMessageBox.warning(self, "更新失败", "银行卡信息更新失败")
                else:
                    QMessageBox.information(self, "无修改", "银行卡信息未修改")

            except Exception as e:
                self.db.rollback()
                QMessageBox.critical(self, "错误", f"更新银行卡信息时出错: {str(e)}")
    def open_account(self):
        dialog = OpenAccountDialog(self.db, self)
        if dialog.exec_() == QDialog.Accepted and dialog.validate():
            try:
                data = dialog.get_data()
                query = """
                CALL OpenAccount(
                    %(p_name)s, %(p_pid)s, %(p_phone)s, 
                    %(p_savingID)s, %(p_openMoney)s, 
                    @p_newCardID, @p_errorMsg
                );
                SELECT @p_errorMsg AS result, @p_newCardID AS card_id;
                """
                result = self.db.execute_query(query, data)
                if result and result[0].get('result'):
                    message = result[0].get('result', '开卡失败')
                    new_card_id = result[0].get('card_id', '未知')
                    if message.startswith("开卡成功"):
                        QMessageBox.information(self, "开卡成功", message)
                        self.load_cards()
                    else:
                        QMessageBox.warning(self, "开卡失败", message)
            except Exception as e:
                QMessageBox.critical(self, "操作失败", f"开卡操作时出错: {str(e)}")

    def report_loss(self):
        if not self.selected_card_id:
            return

        reply = QMessageBox.question(
            self, "确认挂失",
            f"确定要挂失银行卡 {self.selected_card_id} 吗?\n挂失后将无法进行交易",
            QMessageBox.Yes | QMessageBox.No, QMessageBox.No
        )

        if reply == QMessageBox.Yes:
            try:
                query = """
                CALL UpdateCardStatus(
                    %(card_id)s, '挂失', @p_resultMsg
                );
                SELECT @p_resultMsg AS result;
                """
                result = self.db.execute_query(query, {'card_id': self.selected_card_id})
                if result and result[0].get('result'):
                    message = result[0].get('result', '操作失败')
                    if message.endswith("操作成功"):
                        QMessageBox.information(self, "挂失成功", message)
                        self.load_cards()
                    else:
                        QMessageBox.warning(self, "操作失败", message)
            except Exception as e:
                QMessageBox.critical(self, "操作失败", f"挂失操作时出错: {str(e)}")

    def unlock_card(self):
        if not self.selected_card_id:
            return

        reply = QMessageBox.question(
            self, "确认解挂",
            f"确定要解除挂失银行卡 {self.selected_card_id} 吗?\n解挂后恢复交易功能",
            QMessageBox.Yes | QMessageBox.No, QMessageBox.No
        )

        if reply == QMessageBox.Yes:
            try:
                query = """
                CALL UpdateCardStatus(
                    %(card_id)s, '解挂', @p_resultMsg
                );
                SELECT @p_resultMsg AS result;
                """
                result = self.db.execute_query(query, {'card_id': self.selected_card_id})
                if result and result[0].get('result'):
                    message = result[0].get('result', '操作失败')
                    if message.endswith("操作成功"):
                        QMessageBox.information(self, "解挂成功", message)
                        self.load_cards()
                    else:
                        QMessageBox.warning(self, "操作失败", message)
            except Exception as e:
                QMessageBox.critical(self, "操作失败", f"解挂操作时出错: {str(e)}")

    def close_account(self):
        if not self.selected_card_id:
            return

        try:
            # 1. 获取完整的客户信息（含customerID）
            customer_query = """
            SELECT u.customerID, u.customerName, u.PID, u.telephone 
            FROM userInfo u
            JOIN cardInfo c ON u.customerID = c.customerID
            WHERE c.cardID = %s
            """
            customer = self.db.execute_query(customer_query, (self.selected_card_id,))

            if not customer:
                QMessageBox.warning(self, "获取客户信息失败", "未找到银行卡对应的客户信息")
                return

            customer_id = customer[0].get('customerID')
            customer_info = {
                'name': customer[0].get('customerName', ''),
                'pid': customer[0].get('PID', ''),
                'phone': customer[0].get('telephone', ''),
                'id': customer_id
            }

            # 2. 检查总余额
            balance_query = """
            SELECT COALESCE(SUM(balance), 0) as total_balance
            FROM cardInfo
            WHERE customerID = %s
            """
            balance_result = self.db.execute_query(balance_query, (customer_id,))
            total_balance = balance_result[0]['total_balance'] if balance_result else 0

            # 3. 创建销户对话框并传递完整的客户信息
            dialog = CloseAccountDialog(
                self.db,
                total_balance,
                customer_id,
                customer_info,
                self
            )

            # 填充对话框中的客户信息
            dialog.customer_name.setText(customer_info['name'])
            dialog.pid.setText(customer_info['pid'])
            dialog.phone.setText(customer_info['phone'])

            if dialog.exec_() == QDialog.Accepted:
                # 先验证基本输入
                if not dialog.validate():
                    return

                # 有余额时验证转账信息
                if total_balance > 0 and not dialog.validate_with_balance():
                    return

                # 构建参数（无需再次弹出对话框）
                data = {
                    'p_customerName': customer_info['name'],
                    'p_pid': customer_info['pid'],
                    'p_phone': customer_info['phone'],
                    'p_transferToCardID': None  # 初始化为None
                }

                if total_balance > 0:
                    data['p_transferToCardID'] = dialog.transfer_to_card.text().strip()

                # 调用存储过程
                query = """
                           CALL CloseAccountOperation(
                               %(p_customerName)s, 
                               %(p_pid)s, 
                               %(p_phone)s, 
                               %(p_transferToCardID)s,
                               @p_resultMsg
                           );
                           SELECT @p_resultMsg AS result;
                           """

                # 执行查询
                result = self.db.execute_query(query, data)

                # 处理结果
                if result and result[0].get('result'):
                    message = result[0].get('result', '操作失败')
                    if message.startswith("销户成功"):
                        QMessageBox.information(self, "销户成功", message)
                        self.load_cards()
                    else:
                        # 提取具体错误信息
                        error_msg = message.split(":")[-1].strip()
                        QMessageBox.warning(
                            self, "操作失败",
                            f"{error_msg}\n错误代码: {message[:10]}"
                        )


        except Exception as e:
            import traceback
            traceback.print_exc()
            QMessageBox.critical(
                self, "系统异常",
                f"未处理的异常: {str(e)}"
            )